#include <sys/socket.h>
#include <sys/types.h>
#include <iostream>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

#include "Acceptor.h"
#include "Channel.h"
#include "Socket.h"

Socket::~Socket() {
    close(fd_);
}

Acceptor::Acceptor(EventLoop* loop, InetAddress& listenAddr) :
    loop_(loop),
    listenSocket_(Socket::createNonblockSocektOrDie()),
    channel_(new Channel(loop, listenSocket_.getFd())),
    idleFd_(open("/dev/null", O_RDONLY | O_CLOEXEC))
{
    listenSocket_.setReuseAddr(true);
    listenSocket_.setReusePort(true);
    channel_->setReadCallback(std::bind(&Acceptor::handleRead, this));
    listenSocket_.bind(listenAddr);
}

Acceptor::~Acceptor() {
    close(idleFd_);
}

void Acceptor::listen() {
    listenSocket_.listen();
    channel_->enableReading();
}

void Acceptor::handleRead() {
    InetAddress peerAddr;
    int connfd = listenSocket_.accept(&peerAddr);
    if (connfd < 0) {
        if (errno = EMFILE) { // 没有文件描述符可用
            close(idleFd_);
            int tempFd = listenSocket_.accept(&peerAddr);
            close(tempFd);
            idleFd_ = ::open("dev/null", O_RDONLY | O_CLOEXEC);
        }
    } else {
        std::cout << "accpet a connection, fd = " << connfd << ", " << peerAddr.toString() << std::endl;
        newConnectCallback_(connfd, peerAddr);
    }
}
